#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <string.h>
#include <nodelist.h>
#include <threadpool.h>

/*
*	函数功能：		epoll线程主体函数
*	函数参数	：	线程结构体指针
*	函数返回值：不关心
*/
static void *threadPool_work(void *data)
{
	int pos,i,ret;
	struct epoll_event ev[EPOLLEVENTNUM];
	T_threadFun funData;
	PT_threadPool threadPool = data;
	pthread_t tid = pthread_self();
	
	for(i=0;i<THREADNUM;i++)
	{
		if(tid == threadPool->tid[i])
			break;
	}

	if(i>=THREADNUM)
	{
		syslog(LOG_ERR,"threadPool work tid error");
		return NULL;
	}

	pos = i;
	threadPool->epollfd[pos] = epoll_create(10);	
	if(threadPool->epollfd[pos]<0)
	{
		syslog(LOG_ERR,"epollfd:%d create error %s",pos,strerror(errno));
		return NULL;
	}

	while(1)
	{
		ret = epoll_wait(threadPool->epollfd[pos],ev,EPOLLEVENTNUM,-1);
		if(ret < 0)
		{
			if(errno == EINTR)
				continue;
			syslog(LOG_ERR,"epollfd:%d wait error %s",pos,strerror(errno));
			continue;
		}
		else
		{
			for(i=0; i<ret; i++)
			{
				if(ev[i].events & EPOLLIN)
				{
					funData.clientfd 	= ev[i].data.fd;
					funData.pos 		= pos;
					funData.threadPool 	= threadPool;
					ret = threadPool->fun(&funData);
					if(ret <0)
						syslog(LOG_ERR,"epoll data analysis error");
				}
				else
					syslog(LOG_ERR,"epoll events unknown");
			}
		}
	}

	pthread_exit(NULL);
}

/*
*	函数功能：		epoll线程初始化
*	函数参数	：	每个线程需要执行的函数指针
*	函数返回值：线程结构体指针
*				成功：结构体地址
*				失败：NULL
*/
PT_threadPool threadPool_init(FUNC fun)
{
	PT_threadPool threadPool;
	int i,ret;

	threadPool = malloc(sizeof(*threadPool));
	if(threadPool ==NULL)
	{
		syslog(LOG_ERR,"threaPool malloc error");
		return NULL;
	}
	for(i=0;i<THREADNUM;i++)
	{
		threadPool->sumEpollDetectFdNum[i] = 0;
		threadPool->epollfd[i] = -1;
	}

	threadPool->fun = fun;
	pthread_mutex_init(&threadPool->mutex,NULL);
	pthread_cond_init(&threadPool->cond,NULL);
	
	for(i=0;i<THREADNUM;i++)
	{
		ret = pthread_create(&threadPool->tid[i],NULL,threadPool_work,threadPool);
		if(ret !=0)
		{
			syslog(LOG_ERR,"threadPool pthread create error");
			return NULL;
		}
	}

	return threadPool;
}

/*
*	函数功能：		查找监听文件最少的epoll线程
*	函数参数	：	线程结构体指针
*	函数返回值：当前最少监听epoll线程序号
*/
static int findMinEpollPos_unlock(PT_threadPool pool)
{
	int i;
	int pos=0;
	unsigned int num=pool->sumEpollDetectFdNum[0];
	
	for(i=0;i<THREADNUM;i++)
	{
		if(num > pool->sumEpollDetectFdNum[i])
		{
			num = pool->sumEpollDetectFdNum[i];
			pos =i;
		}	
	}
	
	return pos;
}

/*
*	函数功能：		向epoll监视线程中添加监视客户端
*	函数参数	：	1、线程结构体指针    
*				2、客户端文件描述符
*	函数返回值：任务添加是否成功  
*				成功：0
*				失败：<0
*/
int threadPool_addjob(PT_threadPool threadPool,int clientfd)
{
	int pos,ret;
	struct epoll_event ev;

	if(threadPool ==NULL || clientfd <0)
	{
		syslog(LOG_ERR,"threadPool addjob pragram error");
		return -1;
	}
	
	ev.events = EPOLLIN;
	ev.data.fd = clientfd;
	
	pthread_mutex_lock(&threadPool->mutex);

	//查看应该加入哪个epoll监听列表
	pos = findMinEpollPos_unlock(threadPool);

	//加入epoll监听列表中
	ret = epoll_ctl(threadPool->epollfd[pos],EPOLL_CTL_ADD,clientfd,&ev);
	if(ret <0)
	{
		pthread_mutex_unlock(&threadPool->mutex);
		syslog(LOG_ERR,"threadPool addjob epoll_ctl error %s",strerror(errno));
		return -2;
	}
	threadPool->sumEpollDetectFdNum[pos] ++;

	//加入nodeList列表中
	ret = nodeList_addNode_unLock(pos, threadPool->epollfd[pos], clientfd);
	if(ret <0)
	{
		epoll_ctl(threadPool->epollfd[pos],EPOLL_CTL_DEL,clientfd,NULL);
		pthread_mutex_unlock(&threadPool->mutex);
		syslog(LOG_ERR,"threadPool addjob nodeList error %d",ret);
		return -3;
	}
	
	pthread_mutex_unlock(&threadPool->mutex);

	return 0;
}

/*
*	函数功能：		关闭epoll线程销毁锁释放申请的空间
*	函数参数	：	线程结构体指针    
*/
void threadPool_destroy(PT_threadPool threadPool)
{
	int i;

	for(i=0;i<THREADNUM;i++)
	{
		pthread_cancel(threadPool->tid[i]);
		pthread_join(threadPool->tid[i],NULL);
	}
	pthread_mutex_destroy(&threadPool->mutex);
	pthread_cond_destroy(&threadPool->cond);
	free(threadPool);

	syslog(LOG_DEBUG,"threadPool destroy sucess");
}

